跳到主要内容

Shell 脚本使用变量

变量的使用

定义变量时,变量名不加美元符号

your_name="alsritter"

注意,变量名和等号之间不能有空格 。同时,变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线(_)。
  • 不能使用标点符号。
  • 不能使用 bash 里的关键字(可用 help 命令查看保留关键字)。

有效的 Shell 变量名示例如下:

LD_LIBRARY_PATH
_var
var2

除了显式地直接赋值,还可以用语句给变量赋值,如:

for file in `ls /etc`
# 或
for file in $(ls /etc)

以上语句将 /etc 下目录的文件名循环出来。

使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

your_name="alsritter"

echo $your_name
echo ${your_name}
备注

如果想要打印美元符,则使用 \$ 去转义

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done

如果不给 skill 变量加花括号,写成 echo "I am good at $skillScript",解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

推荐给所有变量加上花括号,这是个好的编程习惯。

已定义的变量,可以被重新定义,如:

your_name="tom"
echo $your_name

your_name="alibaba"
echo $your_name

第二次赋值的时候不能写 $your_name="alibaba",使用变量的时候才加美元符 $

为变量赋值

除了直接手动给变量赋值,还可以通过其它命令给变量服务

# 执行 date 命令,并把这个 date 命令传递给 COTENT 变量
CONTENT=$(date +%y%m%d)
echo "Date: ${CONTENT}"

# 虽然也有使用 CONTENT=`date` 这种写法,但是已经过时了

只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl

myUrl="https://www.alsritter.icu"

删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name

unset 命令不能删除只读变量

打印变量的长度

var=12345678901234567890
echo ${#var}

输出

20

字符串

字符串可以用单引号,也可以用双引号,也可以不用引号。

单引号

str='this is a string'

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号

your_name='alsritter'
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str

输出结果为:

Hello, I know you are "alsritter"! 

双引号的优点:

双引号里可以有变量 双引号里可以出现转义字符

多行字符串

#!/bin/bash

var1=100

USAGE=$(cat <<-END
This is line one. ${var1}
This is line two.
This is line three.
END
)

echo "$USAGE"

输出

    This is line one. 100
This is line two.
This is line three.

可以发现这里也能很方便的使用变量 var1

警告

这里 "$USAGE" 一定要加双引号包裹,否则输出的字符串是不换行的

参考 Multi-line string with extra space (preserved indentation)

拼接字符串

your_name="alsritter"

# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3

输出结果为:

hello, alsritter ! hello, alsritter !
hello, alsritter ! hello, ${your_name} !

获取字符串长度

string="abcd"
echo ${#string} #输出 4

提取子字符串

以下实例从字符串第 2 个字符开始截取 4 个字符:

string="alsritter is a great site"
echo ${string:1:4} # 输出 lsri

注意:第一个字符的索引值为 0。

如果想移除最后一个字符

$ var="012345"
$ echo ${var:0:-1}
01234

或者:

var="12345467,"
echo ${var%?}
# 输出结果 12345467

去掉字符串最后两个字符

var="12345467,"
echo ${var%??}
# 输出结果 1234546

删除字符串最后一个逗号

#!/bin/bash
links=("ssssss," "ddddddddddd," "xxxxxxx,")

# 去除最后一个 ,
links[2]=${links[2]%,}
echo "${links[@]}"

输出

ssssss, ddddddddddd, xxxxxxx

查找子字符串

查找子字串的位置

t="MULTI: primary virtual IP for xyz/x.x.x.x:44595: 10.0.0.12"
search="IP for"

# 查找子子串的位置
rest=${t#*$search}

echo $(( ${#t} - ${#rest} - ${#search} )) #输出23

或者这种方式:

text="MULTI: primary virtual IP for xyz/x.x.x.x:44595: 10.0.0.12"
search="IP for"

prefix=${text%%$search*}
echo ${#prefix} #输出23

Shell 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

定义数组

在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 ... 值n)

例如:

array_name=(value0 value1 value2 value3)

或者

array_name=(
value0
value1
value2
value3
)

还可以单独定义数组的各个分量:

array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

可以不使用连续的下标,而且下标的范围没有限制。

读取数组

读取数组元素值的一般格式是:

${数组名[下标]}

例如:

valuen=${array_name[n]}

使用 @ 符号可以获取数组中的所有元素,例如:

echo ${array_name[@]}

为数组添加元素

# Declare a string array
arrVar=("AC" "TV" "Mobile" "Fridge" "Oven" "Blender")

# Add new element at the end of the array
arrVar+=("Dish Washer")

# Iterate the loop to read and print each array element
for value in "${arrVar[@]}"
do
echo $value
done

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

特殊的自带变量

处理上面介绍的变量类型,还有些有特殊作用的自带变量

$#  # 传递到脚本的参数个数
$* # 以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$ # 脚本运行的当前进程ID号
$! # 后台运行的最后一个进程的ID号
$@ # 与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$- # 显示Shell使用的当前选项,与set命令功能相同。
$? # 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

使用例:

#!/bin/bash

echo "Shell 传递参数实例!";
echo "第一个参数为: $1";

echo "参数个数为: $#";
echo "传递的参数作为一个字符串显示: $*";

执行脚本,输出结果如下所示:

$ chmod +x test.sh 
$ ./test.sh 1 2 3
Shell 传递参数实例!
第一个参数为:1
参数个数为:3
传递的参数作为一个字符串显示:1 2 3